﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace AssessmentActions
{
    /// <summary>
    /// Assessment class which contains the test questions. Serializable for storage in the database.
    /// </summary>
    [Serializable()]
    public class Assessment : ISerializable
    {
        private int _id;
        private string _name;
        private DateTime _createdDate;
        private List<Question> _questions;
        private string _html;
        private string _xml;

        /// <summary>
        /// Constructor. Initilizes the questions list.
        /// </summary>
        public Assessment()
        {
            _questions = new List<Question>();
        }

        /// <summary>
        /// Returns HTML representation of the assessment
        /// </summary>
        /// <returns>Assessment as HTML string</returns>
        public string getAssessmentHtml()
        {
            buildHtml(false);
            return this._html;
        }

        /// <summary>
        /// Returns XML representation of the assessment with the answers marked
        /// </summary>
        /// <returns>Assessment as HTML string</returns>
        public string getAssessmentHtmlWithAnswers()
        {
            buildHtml(true);
            return this._html;
        }

        public string getAssessmentHtmlWithSelectors()
        {
            buildHtmlWithSelectors();
            return this._html;
        }

        /// <summary>
        /// Returns HTML representation of the assessment
        /// </summary>
        /// <returns>Assessment as XML string</returns>
        public string getAssessmentXml()
        {
            buildXML(false);
            return this._xml;
        }

        /// <summary>
        /// Returns XML representation of the assessment with the answers marked
        /// </summary>
        /// <returns>Assessment as XML string</returns>
        public string getAssessmentXmlWithAnswers()
        {
            buildXML(true);
            return this._xml;
        }

        /// <summary>
        /// Builds the assessment HTML
        /// </summary>
        /// <param name="includeAnswers">True if answers are to be included</param>
        private void buildHtml(bool includeAnswers)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("<div id=\"assessment\">");
            sb.Append("<span id=\"name\">" + _name + "</span>");
            sb.Append("<span id=\"assessmentId\">" + _id + "</span>");
            sb.Append("<span id=\"date\">" + _createdDate.ToString("MM/dd/yyyy HH:mm:ss") + "</span>");
            foreach (Question question in _questions)
            {
                if (includeAnswers)
                    sb.Append(question.getQuestionWithAnswerHtml());
                else
                    sb.Append(question.getQuestionHtml());
            }
            sb.Append("</div>");
            this._html = sb.ToString();
        }

        /// <summary>
        /// Builds the assessment HTML for test
        /// </summary>
        private void buildHtmlWithSelectors()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("<div id=\"assessment\">");
            sb.Append("<input type=\"text\" class=\"assesmentName\" id=\"assessmentName\" name=\"assessmentName\" value=\"" + _name + "\" />");
            sb.Append("<input type=\"text\" class=\"assessmentId\" id=\"assessmentId\" name=\"assessmentId\" value=\"" + this._id + "\" />");
            sb.Append("<span id=\"date\">" + _createdDate.ToString("MM/dd/yyyy HH:mm:ss") + "</span>");
            foreach (Question question in _questions)
            {
                sb.Append(question.getQuestionHtmlWithSelector());
            }
            sb.Append("</div>");
            this._html = sb.ToString();
        }

        /// <summary>
        /// Builds the assessment XML
        /// </summary>
        /// <param name="includeAnswers">True if answers are to be included</param>
        private void buildXML(bool includeAnswers)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
            sb.Append("\n<assessment>");
            sb.Append("\n\t<name>" + _name + "</name>");
            sb.Append("\n\t<assessmentId>" + _id + "</assessmentId>");
            sb.Append("\n\t<date>" + _createdDate.ToString("MM/dd/yyyy HH:mm:ss") + "</date>");
            foreach (Question question in _questions)
            {
                if (includeAnswers)
                    sb.Append(question.getQuestionWithAnswerXml());
                else
                    sb.Append(question.getQuestionXml());
            }
            sb.Append("\n</assessment>");
            this._xml = sb.ToString();
        }

        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public DateTime CreatedDate
        {
            get { return _createdDate; }
            set { _createdDate = value; }
        }

        /// <summary>
        /// Adds a question to the assessment
        /// </summary>
        /// <param name="newQuestion">Question to be added.</param>
        public void addQuestion(Question newQuestion)
        {
            _questions.Add(newQuestion);
        }

        /// <summary>
        /// Calculates the final grade of an assessment.
        /// </summary>
        /// <param name="answers">String of answers separated with a pipe "|". Uses T or F for true false questions.
        /// Uses a zero based int for multiple choice questions.</param>
        /// <returns>String containing the final grade.</returns>
        public string getGrade(string answers)
        {
            int numberOfQuestions = _questions.Count;
            decimal cumulativeTotal = 0;

            int i = 0;
            string[] answersSplit = answers.Split('|');
            foreach (string answer in answersSplit)
            {
                if (_questions[i++].getCorrectAnswer() == answer)
                    cumulativeTotal++;
            }

            decimal finalGradePercent = (cumulativeTotal / numberOfQuestions) * 100;
            return finalGradePercent.ToString();
        }

        public string getCorrectAnswers()
        {
            string results = "";
            
            foreach (Question question in _questions)
            {
                results += question.getCorrectAnswer() + "|";
            }

            return results;
        }

        /// <summary>
        /// Deserialization constructor
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public Assessment(SerializationInfo info, StreamingContext ctxt)
        {
            _id = (int)info.GetValue("_id", typeof(int));
            _name = (String)info.GetValue("_name", typeof(String));
            _questions = (List<Question>)info.GetValue("_questions", typeof(List<Question>));
            _createdDate = (DateTime)info.GetValue("_createdDate", typeof(DateTime));

        }

        /// <summary>
        /// Serialization function
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("_id", _id);
            info.AddValue("_name", _name);
            info.AddValue("_questions", _questions);
            info.AddValue("_createdDate", _createdDate);
        }
    }

}
